using NGIS.Data.Schema;
using System;
using System.Collections.Generic;
using System.Xml;

namespace NGIS.Model
{
	public class ModelBehavior : IModelBehavior
	{
		private List<ModelDatasetItem> mModelDatasetItemList = new List<ModelDatasetItem>();

		private List<ModelState> mModelStateList = new List<ModelState>();

		private List<ModelStateTransition> mModelStateTransitionList = new List<ModelStateTransition>();

		private List<ModelParameter> mProcessParameters = new List<ModelParameter>();

		private List<ModelParameter> mControlParameters = new List<ModelParameter>();

		public bool loadFromXml(XmlElement pModelClassElement)
		{
			XmlElement xmlElement = (XmlElement)pModelClassElement.ChildNodes[1];
			XmlNodeList elementsByTagName = xmlElement.GetElementsByTagName("RelatedDatasets");
			if (elementsByTagName.Count > 0)
			{
				XmlElement xmlElement2 = (XmlElement)elementsByTagName[0];
				for (int i = 0; i < xmlElement2.ChildNodes.Count; i++)
				{
					XmlElement xmlElement3 = (XmlElement)xmlElement2.ChildNodes[i];
					ModelDatasetItem pDataset = default(ModelDatasetItem);
					pDataset.datasetName = xmlElement3.GetAttribute("name");
					pDataset.datasetItemDescription = xmlElement3.GetAttribute("description");
					string attribute = xmlElement3.GetAttribute("type");
					if (attribute == "internal")
					{
						pDataset.datasetItemType = EModelDatasetItemType.EMDIT_INTERNAL;
						pDataset.externalId = "";
						UdxDatasetSchema udxDatasetSchema = new UdxDatasetSchema(null, "UdxDeclaration");
						udxDatasetSchema.LoadFromXmlElement(xmlElement3.FirstChild as XmlElement);
						pDataset.datasetItem = udxDatasetSchema;
					}
					else if (attribute == "external")
					{
						pDataset.datasetItemType = EModelDatasetItemType.EMDIT_EXTERNAL;
						pDataset.externalId = xmlElement3.GetAttribute("externalId");
						pDataset.datasetItem = null;
					}
					else if (attribute == "raw")
					{
						pDataset.datasetItemType = EModelDatasetItemType.EMDIT_RAW;
						pDataset.externalId = "";
						pDataset.datasetItem = null;
					}
					addModelDatasetItem(ref pDataset);
				}
			}
			XmlNodeList elementsByTagName2 = xmlElement.GetElementsByTagName("States");
			if (elementsByTagName.Count > 0)
			{
				XmlElement xmlElement4 = (XmlElement)elementsByTagName2[0];
                XmlElement xmlElement5 = xmlElement4;
				for (int j = 0; j < xmlElement5.ChildNodes.Count; j++)
				{
					XmlElement xmlElement6 = (XmlElement)xmlElement5.ChildNodes[j];
					ModelState pState = default(ModelState);
					pState.stateId = xmlElement6.GetAttribute("id");
					pState.stateName = xmlElement6.GetAttribute("name");
					pState.stateDecription = xmlElement6.GetAttribute("description");
					string attribute2 = xmlElement6.GetAttribute("type");
					if (attribute2 == "basic")
					{
						pState.stateType = EModelStateType.EMST_BASIC;
					}
					else if (attribute2 == "group")
					{
						pState.stateType = EModelStateType.EMST_GROUP;
					}
                    pState.modelEvents = new List<ModelEvent>();
					for (int k = 0; k < xmlElement6.ChildNodes.Count; k++)
					{
						XmlElement xmlElement7 = (XmlElement)xmlElement6.ChildNodes[k];
						ModelEvent item = default(ModelEvent);
						item.eventName = xmlElement7.GetAttribute("name");
						item.eventDescription = xmlElement7.GetAttribute("description");
						string attribute3 = xmlElement7.GetAttribute("type");
						if (attribute3 == "response")
						{
							item.eventType = EModelEventType.EMET_RESPONSE;
						}
						else if (attribute3 == "noresponse")
						{
							item.eventType = EModelEventType.EMET_NORESPONSE;
						}
						else if (attribute3 == "control")
						{
							item.eventType = EModelEventType.EMET_CONTROL;
						}
						XmlElement xmlElement8 = (XmlElement)xmlElement7.FirstChild;
						if (xmlElement8.HasAttribute("description"))
						{
							item.parameterDescription = xmlElement8.GetAttribute("description");
						}
						else
						{
							item.parameterDescription = "";
						}
						item.datasetReference = xmlElement8.GetAttribute("datasetReference");
						string attribute4 = xmlElement7.GetAttribute("optional");
						if (attribute4 == "")
						{
							item.optional = false;
						}
						else
						{
							item.optional = Convert.ToBoolean(attribute4);
						}
						pState.modelEvents.Add(item);
					}
					addModelState(ref pState);
				}
				XmlElement xmlElement9 = (XmlElement)xmlElement4.ChildNodes[1];
                if (xmlElement9 != null)
                {
                    for (int l = 0; l < xmlElement9.ChildNodes.Count; l++)
                    {
                        XmlElement xmlElement10 = (XmlElement)xmlElement9.ChildNodes[l];
                        string attribute5 = xmlElement10.GetAttribute("from");
                        string attribute6 = xmlElement10.GetAttribute("to");
                        addModelStateTransition(attribute5, attribute6);
                    }
                }
			}
			XmlNodeList elementsByTagName3 = xmlElement.GetElementsByTagName("RelatedDatasets");
			if (elementsByTagName.Count > 0)
			{
				XmlElement xmlElement11 = (XmlElement)elementsByTagName3[0];
				XmlElement xmlElement12 = (XmlElement)xmlElement11.ChildNodes[0];
				foreach (XmlElement childNode in xmlElement12.ChildNodes)
				{
					ModelParameter item2 = default(ModelParameter);
					item2.Key = childNode.GetAttribute("key");
					item2.Description = childNode.GetAttribute("description");
					item2.DefaultValue = childNode.GetAttribute("defaultValue");
					mProcessParameters.Add(item2);
				}
                XmlElement xmlElement14 = (XmlElement)xmlElement11.ChildNodes[1];
                if (xmlElement14 != null)
                {
                    foreach (XmlElement childNode2 in xmlElement14.ChildNodes)
                    {
                        ModelParameter item3 = default(ModelParameter);
                        item3.Key = childNode2.GetAttribute("key");
                        item3.Description = childNode2.GetAttribute("description");
                        item3.DefaultValue = childNode2.GetAttribute("defaultValue");
                        mProcessParameters.Add(item3);
                    }
                }
			}
			return true;
		}

		public bool formatToXml(XmlElement pModelClassElement)
		{
			XmlDocument ownerDocument = pModelClassElement.OwnerDocument;
			XmlElement xmlElement = ownerDocument.CreateElement("Behavior");
			XmlElement xmlElement2 = ownerDocument.CreateElement("RelatedDatasets");
			XmlElement xmlElement3 = ownerDocument.CreateElement("StateGroup");
			XmlElement xmlElement4 = ownerDocument.CreateElement("Parameters");
			for (int i = 0; i < mModelDatasetItemList.Count; i++)
			{
				ModelDatasetItem modelDatasetItem = mModelDatasetItemList[i];
				XmlElement xmlElement5 = ownerDocument.CreateElement("DatasetItem");
				xmlElement5.SetAttribute("name", modelDatasetItem.datasetName);
				if (modelDatasetItem.datasetItemType == EModelDatasetItemType.EMDIT_EXTERNAL)
				{
					xmlElement5.SetAttribute("type", "external");
					xmlElement5.SetAttribute("externalId", modelDatasetItem.externalId);
					xmlElement5.SetAttribute("description", modelDatasetItem.datasetItemDescription);
				}
				else if (modelDatasetItem.datasetItemType == EModelDatasetItemType.EMDIT_INTERNAL)
				{
					xmlElement5.SetAttribute("type", "internal");
					xmlElement5.SetAttribute("description", modelDatasetItem.datasetItemDescription);
					if (modelDatasetItem.datasetItem != null)
					{
						modelDatasetItem.datasetItem.FormatToXmlElement(ref xmlElement5);
					}
				}
				else if (modelDatasetItem.datasetItemType == EModelDatasetItemType.EMDIT_RAW)
				{
					xmlElement5.SetAttribute("type", "raw");
					xmlElement5.SetAttribute("description", modelDatasetItem.datasetItemDescription);
				}
				xmlElement2.AppendChild(xmlElement5);
			}
			XmlElement xmlElement6 = ownerDocument.CreateElement("States");
			xmlElement3.AppendChild(xmlElement6);
			for (int j = 0; j < mModelStateList.Count; j++)
			{
				ModelState modelState = mModelStateList[j];
				XmlElement xmlElement7 = ownerDocument.CreateElement("State");
				xmlElement7.SetAttribute("id", modelState.stateId);
				xmlElement7.SetAttribute("name", modelState.stateName);
				if (modelState.stateType == EModelStateType.EMST_BASIC)
				{
					xmlElement7.SetAttribute("type", "basic");
				}
				else if (modelState.stateType == EModelStateType.EMST_GROUP)
				{
					xmlElement7.SetAttribute("type", "group");
				}
				else
				{
					xmlElement7.SetAttribute("type", "unknown");
				}
				xmlElement7.SetAttribute("description", modelState.stateDecription);
				for (int k = 0; k < modelState.modelEvents.Count; k++)
				{
					ModelEvent modelEvent = modelState.modelEvents[k];
					EModelEventType eventType = modelEvent.eventType;
					XmlElement xmlElement8 = ownerDocument.CreateElement("Event");
					xmlElement8.SetAttribute("name", modelEvent.eventName);
					switch (eventType)
					{
					case EModelEventType.EMET_RESPONSE:
					{
						xmlElement8.SetAttribute("type", "response");
						XmlElement xmlElement11 = ownerDocument.CreateElement("ResponseParameter");
						xmlElement11.SetAttribute("datasetReference", modelEvent.datasetReference);
						xmlElement11.SetAttribute("description", modelEvent.parameterDescription);
						xmlElement8.AppendChild(xmlElement11);
						break;
					}
					case EModelEventType.EMET_NORESPONSE:
					{
						xmlElement8.SetAttribute("type", "noresponse");
						XmlElement xmlElement10 = ownerDocument.CreateElement("DispatchParameter");
						xmlElement10.SetAttribute("datasetReference", modelEvent.datasetReference);
						xmlElement10.SetAttribute("description", modelEvent.parameterDescription);
						xmlElement8.AppendChild(xmlElement10);
						break;
					}
					case EModelEventType.EMET_CONTROL:
					{
						xmlElement8.SetAttribute("type", "control");
						XmlElement xmlElement9 = ownerDocument.CreateElement("ControlParameter");
						xmlElement9.SetAttribute("datasetReference", modelEvent.datasetReference);
						xmlElement9.SetAttribute("description", modelEvent.parameterDescription);
						xmlElement8.AppendChild(xmlElement9);
						break;
					}
					}
					xmlElement8.SetAttribute("optional", modelEvent.optional.ToString());
					xmlElement8.SetAttribute("description", modelEvent.eventDescription);
					xmlElement7.AppendChild(xmlElement8);
				}
				xmlElement6.AppendChild(xmlElement7);
			}
			XmlElement xmlElement12 = ownerDocument.CreateElement("StateTransitions");
			xmlElement3.AppendChild(xmlElement12);
			foreach (ModelStateTransition mModelStateTransition in mModelStateTransitionList)
			{
				string stateId = mModelStateTransition.fromState.stateId;
				string stateId2 = mModelStateTransition.toState.stateId;
				XmlElement xmlElement13 = ownerDocument.CreateElement("Add");
				xmlElement13.SetAttribute("from", stateId);
				xmlElement13.SetAttribute("to", stateId2);
				xmlElement12.AppendChild(xmlElement13);
			}
			XmlElement xmlElement14 = ownerDocument.CreateElement("ProcessParameters");
			foreach (ModelParameter mProcessParameter in mProcessParameters)
			{
				XmlElement xmlElement15 = ownerDocument.CreateElement("Add");
				xmlElement15.SetAttribute("key", mProcessParameter.Key);
				xmlElement15.SetAttribute("description", mProcessParameter.Description);
				xmlElement15.SetAttribute("defaultValue", mProcessParameter.DefaultValue);
				xmlElement14.AppendChild(xmlElement15);
			}
			xmlElement4.AppendChild(xmlElement14);
			XmlElement xmlElement16 = ownerDocument.CreateElement("ControlParameters");
			foreach (ModelParameter mControlParameter in mControlParameters)
			{
				XmlElement xmlElement17 = ownerDocument.CreateElement("Add");
				xmlElement17.SetAttribute("key", mControlParameter.Key);
				xmlElement17.SetAttribute("description", mControlParameter.Description);
				xmlElement17.SetAttribute("defaultValue", mControlParameter.DefaultValue);
				xmlElement16.AppendChild(xmlElement17);
			}
			xmlElement4.AppendChild(xmlElement16);
			xmlElement.AppendChild(xmlElement2);
			xmlElement.AppendChild(xmlElement3);
			xmlElement.AppendChild(xmlElement4);
			pModelClassElement.AppendChild(xmlElement);
			return true;
		}

		public bool addModelDatasetItem(ref ModelDatasetItem pDataset)
		{
			for (int i = 0; i < mModelDatasetItemList.Count; i++)
			{
				if (mModelDatasetItemList[i].datasetName == pDataset.datasetName)
				{
					return false;
				}
			}
			mModelDatasetItemList.Add(pDataset);
			return true;
		}

		public bool removeModelDatasetItem(ref ModelDatasetItem pDataset)
		{
			if (mModelDatasetItemList.Contains(pDataset))
			{
				mModelDatasetItemList.Remove(pDataset);
				return true;
			}
			return false;
		}

		public int getModelDatasetItemCount()
		{
			return mModelDatasetItemList.Count;
		}

		public bool getModelDatasetItem(int idx, ref ModelDatasetItem pDataset)
		{
			if (idx < 0 || idx >= mModelDatasetItemList.Count)
			{
				return false;
			}
			pDataset = mModelDatasetItemList[idx];
			return true;
		}

		public bool getModelDatasetItem(string pName, ref ModelDatasetItem pDataset)
		{
			for (int i = 0; i < mModelDatasetItemList.Count; i++)
			{
				if (mModelDatasetItemList[i].datasetName == pName)
				{
					pDataset = mModelDatasetItemList[i];
					return true;
				}
			}
			return false;
		}

		public bool updateModelDatasetItem(int idx, ref ModelDatasetItem pDataset)
		{
			if (idx < 0 || idx >= mModelDatasetItemList.Count)
			{
				return false;
			}
			mModelDatasetItemList[idx] = pDataset;
			return true;
		}

		public bool addModelState(ref ModelState pState)
		{
			for (int i = 0; i < mModelStateList.Count; i++)
			{
				if (mModelStateList[i].stateId == pState.stateId)
				{
					return false;
				}
			}
			mModelStateList.Add(pState);
			return true;
		}

		public bool removeModelState(ref ModelState pState)
		{
			if (mModelStateList.Contains(pState))
			{
				mModelStateList.Remove(pState);
			}
			return false;
		}

		public int getModelStateCount()
		{
			return mModelStateList.Count;
		}

		public bool getModelState(int idx, ref ModelState pState)
		{
			if (idx < 0 || idx >= mModelStateList.Count)
			{
				return false;
			}
			pState = mModelStateList[idx];
			return true;
		}

		public bool getModelState(string pStateId, ref ModelState pState)
		{
			for (int i = 0; i < mModelStateList.Count; i++)
			{
				if (mModelStateList[i].stateId == pStateId)
				{
					pState = mModelStateList[i];
					return true;
				}
			}
			return false;
		}

		public bool updateModelState(int idx, ref ModelState pState)
		{
			if (idx < 0 || idx >= mModelStateList.Count)
			{
				return false;
			}
			mModelStateList[idx] = pState;
			return true;
		}

		public bool updateModelState(string pStateId, ref ModelState pState)
		{
			for (int i = 0; i < mModelStateList.Count; i++)
			{
				if (mModelStateList[i].stateId == pStateId)
				{
					mModelStateList[i] = pState;
					return true;
				}
			}
			return false;
		}

		public bool addModelStateTransition(string pFromStateId, string pToStateId)
		{
			ModelState pState = default(ModelState);
			ModelState pState2 = default(ModelState);
			bool modelState = getModelState(pFromStateId, ref pState);
			bool modelState2 = getModelState(pToStateId, ref pState2);
			if (modelState && modelState2)
			{
				for (int i = 0; i < mModelStateTransitionList.Count; i++)
				{
					if (mModelStateTransitionList[i].fromState.stateId == pFromStateId && mModelStateTransitionList[i].toState.stateId == pToStateId)
					{
						return false;
					}
				}
				ModelStateTransition item = default(ModelStateTransition);
				item.fromState = pState;
				item.toState = pState2;
				mModelStateTransitionList.Add(item);
				return true;
			}
			return false;
		}

		public bool addModelStateTransition(ref ModelState pFromState, ref ModelState pToState)
		{
			return addModelStateTransition(pFromState.stateId, pToState.stateId);
		}

		public bool removeModelStateTransition(string pFromStateId, string pToStateId)
		{
			for (int i = 0; i < mModelStateTransitionList.Count; i++)
			{
				ModelStateTransition item = mModelStateTransitionList[i];
				if (item.fromState.stateId == pFromStateId && item.toState.stateId == pToStateId)
				{
					mModelStateTransitionList.Remove(item);
					return true;
				}
			}
			return false;
		}

		public bool removeModelStateTransition(ref ModelState pFromState, ref ModelState pToState)
		{
			return removeModelStateTransition(pFromState.stateId, pToState.stateId);
		}

		public int getModelStateTransitionCount()
		{
			return mModelStateTransitionList.Count;
		}

		public bool getModelStateTransition(int idx, ref ModelState pFromState, ref ModelState pToState)
		{
			if (idx < 0 || idx >= mModelStateTransitionList.Count)
			{
				return false;
			}
			ModelStateTransition modelStateTransition = mModelStateTransitionList[idx];
			pFromState = modelStateTransition.fromState;
			pToState = modelStateTransition.toState;
			return true;
		}

		public bool getModelStateTransition(int idx, ref ModelStateTransition pStateTransition)
		{
			if (idx < 0 || idx >= mModelStateTransitionList.Count)
			{
				return false;
			}
			pStateTransition = mModelStateTransitionList[idx];
			return true;
		}

		public bool existModelStatetTransition(string pFromStateId, string pToStateId)
		{
			for (int i = 0; i < mModelStateTransitionList.Count; i++)
			{
				ModelStateTransition modelStateTransition = mModelStateTransitionList[i];
				if (modelStateTransition.fromState.stateId == pFromStateId && modelStateTransition.toState.stateId == pToStateId)
				{
					return true;
				}
			}
			return false;
		}

		public bool existModelStatetTransition(ref ModelState pFromState, ref ModelState pToState)
		{
			return existModelStatetTransition(pFromState.stateId, pToState.stateId);
		}

		public bool updateModelStateTransition(int idx, string pFromStateId, string pToStateId)
		{
			if (idx < 0 || idx >= mModelStateTransitionList.Count)
			{
				return false;
			}
			ModelStateTransition pStateTransition = default(ModelStateTransition);
			getModelStateTransition(idx, ref pStateTransition);
			removeModelStateTransition(ref pStateTransition.fromState, ref pStateTransition.toState);
			addModelStateTransition(pFromStateId, pToStateId);
			return true;
		}

		public bool compareOther(IModelBehavior pBehavior, ref string obj, ref string name)
		{
			if (mModelDatasetItemList.Count != pBehavior.getModelDatasetItemCount())
			{
				obj = "RelatedDatasets";
				name = "DatasetItemCount";
				return false;
			}
			for (int i = 0; i < mModelDatasetItemList.Count; i++)
			{
				ModelDatasetItem modelDatasetItem = mModelDatasetItemList[i];
				ModelDatasetItem pDataset = default(ModelDatasetItem);
				pBehavior.getModelDatasetItem(i, ref pDataset);
				if (!modelDatasetItem.compareOther(pDataset))
				{
					obj = "DatasetItem";
					name = modelDatasetItem.datasetName + "<->" + pDataset.datasetName;
					return false;
				}
			}
			if (mModelStateList.Count != pBehavior.getModelStateCount())
			{
				obj = "States";
				name = "StateCount";
				return false;
			}
			for (int j = 0; j < mModelStateList.Count; j++)
			{
				ModelState modelState = mModelStateList[j];
				ModelState pState = default(ModelState);
				pBehavior.getModelState(j, ref pState);
				if (!modelState.compareOther(pState))
				{
					obj = "State";
					name = modelState.stateName + "<->" + pState.stateName;
					return false;
				}
			}
			if (mModelStateTransitionList.Count != pBehavior.getModelStateTransitionCount())
			{
				obj = "StateTransitions";
				name = "StateTransitionCount";
				return false;
			}
			for (int k = 0; k < mModelStateTransitionList.Count; k++)
			{
				ModelStateTransition modelStateTransition = mModelStateTransitionList[k];
				ModelStateTransition pStateTransition = default(ModelStateTransition);
				pBehavior.getModelStateTransition(k, ref pStateTransition);
				if (!modelStateTransition.compareOther(pStateTransition))
				{
					obj = "StateTransition";
					name = modelStateTransition.fromState.stateId + "<->" + pStateTransition.fromState.stateId;
					return false;
				}
			}
			return true;
		}

		public bool addProcessParameter(ModelParameter processparameter)
		{
			if (!mProcessParameters.Contains(processparameter))
			{
				mProcessParameters.Add(processparameter);
			}
			return true;
		}

		public bool getProcessParameter(string key, ref ModelParameter parameter)
		{
			for (int i = 0; i < mProcessParameters.Count; i++)
			{
				if (mProcessParameters[i].Key == key)
				{
					parameter = mProcessParameters[i];
					return true;
				}
			}
			return false;
		}

		public int getProcessParameterCount()
		{
			return mProcessParameters.Count;
		}

		public bool removeProcessParameter(ModelParameter processparameter)
		{
			return mProcessParameters.Remove(processparameter);
		}

		public bool updateProcessParameter(ModelParameter processparameter)
		{
			for (int i = 0; i < mProcessParameters.Count; i++)
			{
				if (mProcessParameters[i].Key == processparameter.Key)
				{
					mProcessParameters[i] = processparameter;
					return true;
				}
			}
			return false;
		}

		public bool addControlParameter(ModelParameter controlparameter)
		{
			if (!mControlParameters.Contains(controlparameter))
			{
				mControlParameters.Add(controlparameter);
			}
			return true;
		}

		public bool getControlParameter(string key, ref ModelParameter parameter)
		{
			for (int i = 0; i < mControlParameters.Count; i++)
			{
				if (mControlParameters[i].Key == key)
				{
					parameter = mControlParameters[i];
					return true;
				}
			}
			return false;
		}

		public int getControlParameterCount()
		{
			return mControlParameters.Count;
		}

		public bool removeControlParameter(ModelParameter controlparameter)
		{
			return mControlParameters.Remove(controlparameter);
		}

		public bool updateControlParameter(ModelParameter controlparameter)
		{
			for (int i = 0; i < mControlParameters.Count; i++)
			{
				if (mControlParameters[i].Key == controlparameter.Key)
				{
					mControlParameters[i] = controlparameter;
					return true;
				}
			}
			return false;
		}
	}
}
